#include "sock5client.hpp"
#include "connectiobuffer.hpp"
#include "logger.hpp"
#include "singleton.hpp"
#include "sock5clientmgr.hpp"
#include <vector>

namespace oraysock5 {
Sock5Client::Sock5Client(std::shared_ptr<IPAddress> remote_addr,
    std::shared_ptr<IPAddress> listen_addr,
    std::shared_ptr<EventBuffer> iobuf)
    : AcceptNewFd(remote_addr, listen_addr, iobuf)
{
    LOG_INFO << "新客户端连接 [ip:" << remote_addr->ip() << ":" << remote_addr->port() << "]";
}

Sock5Client::~Sock5Client()
{
    std::string str;
    if (active_ == CloseType::SERVER_CLOSE) {
        str = "服务器Sock5主动关闭连接";
    } else {
        str = "客户端主动关闭连接";
    }
    LOG_INFO << str << "[ip:" << remote_addr()->ip() << ":" << remote_addr()->port() << "]";
}

void Sock5Client::close(CloseType active)
{
    active_ = active;
    Singleton<Sock5ClientMgr>::instance().remove(iobuf()->fd());
}

void Sock5Client::timerout(CloseType active)
{
    LOG_INFO << "检测到与客户端没有心跳超时 [ip:" << remote_addr()->ip() << ":" << remote_addr()->port() << "]";
    close(active);
}

InputResult Sock5Client::input()
{
    std::shared_ptr<Streambuff> inputbuffer = iobuf()->inputbuffer();
    if (state_ == State::INIT) {
        char recv[3] = { 0 };
        inputbuffer->remove(&recv, sizeof(recv));
        if (recv[0] == 0x05 && recv[2] == 0x00) {
            char send[2];
            send[0] = 0x05;
            send[1] = 0x00;
            iobuf()->write(&send, sizeof(send));
            state_ = State::CONNECT;
        } else {
            LOG_INFO << "协议版本[" << recv[0] << "]或者认证方式不支持[" << recv[2] << "]";
            return InputResult::PASSIVE_CLOSE;
        }
    } else if (state_ == State::CONNECT) {
        char recv[4] = { 0 };
        inputbuffer->remove(&recv, sizeof(recv));
        if (recv[0] == 0x05 && recv[1] == 0x01) {
            //连接上游服务器
            if (recv[3] == 0x01) {
                //ipv4
                unsigned char ip[4];
                inputbuffer->remove(&ip, sizeof(ip));
                uint16_t port;
                inputbuffer->remove(&port, sizeof(port));
                port = ntohs(port);
                std::string ipstr = str_format("%d.%d.%d.%d", *ip, *(ip + 1), *(ip + 2), *(ip + 3));
                std::shared_ptr<IPAddress> ipaddr = std::make_shared<IPAddress>(ipstr.c_str(), port);
                struct sockaddr* address = (struct sockaddr*)ipaddr->sockaddr();

                connector_ = std::make_shared<Connector>(ipaddr);
                connector_->set_client(shared_from_this());
                std::shared_ptr<ConnectIoBuffer> buffer
                    = std::make_shared<ConnectIoBuffer>(iobuf()->base());

                buffer->set_cnev(connector_);
                connector_->set_iobuf(buffer);

                if (bufferevent_socket_connect(buffer->buffer(), address, sizeof(sockaddr_storage)) == -1) {
                    char send[] = { 0x05, 0x01, 0x00, 0x01 };
                    buffer->write(send, sizeof(send));
                }
                state_ = State::EXCHANGEDATA;
            } else {
                LOG_INFO << "目标服务器地址类型方式不支持[" << recv[3] << "]";
            }
        } else {
            LOG_INFO << "协议版本[" << recv[0] << "]或者命令方式不支持[" << recv[2] << "]";
            return InputResult::PASSIVE_CLOSE;
        }
    } else {
        connector_->iobuf()->write(inputbuffer);
    }
    return InputResult::SUCCESS;
}

}
